﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace yaip {
    class Convolution {


        public static bool ConvolutionRadius1(Bitmap image, ConvolutionMatrix matrix) {
            // Avoid divide by zero errors
            if (0 == matrix.getFactor()) return false;

            Bitmap bSrc = (Bitmap)image.Clone();

            // GDI+ still lies to us - the return format is BGR, NOT RGB.
            BitmapData bmData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmData.Stride;
            int stride2 = stride * 2;
            System.IntPtr Scan0 = bmData.Scan0;
            System.IntPtr SrcScan0 = bmSrc.Scan0;

            unsafe {
                byte* p = (byte*)(void*)Scan0;
                byte* pSrc = (byte*)(void*)SrcScan0;

                int nOffset = stride - image.Width * 3;
                int nWidth = image.Width - 2;
                int nHeight = image.Height - 2;

                int nPixel;

                for (int y = 0; y < nHeight; ++y) {
                    for (int x = 0; x < nWidth; ++x) {
                        nPixel = ((((pSrc[2] * matrix.getMatrixValue(0, 0)) +
                                    (pSrc[5] * matrix.getMatrixValue(0, 1)) +
                                    (pSrc[8] * matrix.getMatrixValue(0, 2)) +
                                    (pSrc[2 + stride] * matrix.getMatrixValue(1, 0)) +
                                    (pSrc[5 + stride] * matrix.getMatrixValue(1, 1)) +
                                    (pSrc[8 + stride] * matrix.getMatrixValue(1, 2)) +
                                    (pSrc[2 + stride2] * matrix.getMatrixValue(2, 0)) +
                                    (pSrc[5 + stride2] * matrix.getMatrixValue(2, 1)) +
                                    (pSrc[8 + stride2] * matrix.getMatrixValue(2, 2))) / matrix.getFactor()) + matrix.getOffset());

                        if (nPixel < 0) nPixel = 0;
                        if (nPixel > 255) nPixel = 255;
                        p[5 + stride] = (byte)nPixel;


                        nPixel = ((((pSrc[1] * matrix.getMatrixValue(0, 0)) +
                                    (pSrc[4] * matrix.getMatrixValue(0, 1)) +
                                    (pSrc[7] * matrix.getMatrixValue(0, 2)) +
                                    (pSrc[1 + stride] * matrix.getMatrixValue(1, 0)) +
                                    (pSrc[4 + stride] * matrix.getMatrixValue(1, 1)) +
                                    (pSrc[7 + stride] * matrix.getMatrixValue(1, 2)) +
                                    (pSrc[1 + stride2] * matrix.getMatrixValue(2, 0)) +
                                    (pSrc[4 + stride2] * matrix.getMatrixValue(2, 1)) +
                                    (pSrc[7 + stride2] * matrix.getMatrixValue(2, 2))) / matrix.getFactor()) + matrix.getOffset());

                        if (nPixel < 0) nPixel = 0;
                        if (nPixel > 255) nPixel = 255;
                        p[4 + stride] = (byte)nPixel;


                        nPixel = ((((pSrc[0] * matrix.getMatrixValue(0, 0)) +
                                    (pSrc[3] * matrix.getMatrixValue(0, 1)) +
                                    (pSrc[6] * matrix.getMatrixValue(0, 2)) +
                                    (pSrc[0 + stride] * matrix.getMatrixValue(1, 0)) +
                                    (pSrc[3 + stride] * matrix.getMatrixValue(1, 1)) +
                                    (pSrc[6 + stride] * matrix.getMatrixValue(1, 2)) +
                                    (pSrc[0 + stride2] * matrix.getMatrixValue(2, 0)) +
                                    (pSrc[3 + stride2] * matrix.getMatrixValue(2, 1)) +
                                    (pSrc[6 + stride2] * matrix.getMatrixValue(2, 2))) / matrix.getFactor()) + matrix.getOffset());

                        if (nPixel < 0) nPixel = 0;
                        if (nPixel > 255) nPixel = 255;
                        p[3 + stride] = (byte)nPixel;

                        //Move the pointers...
                        p += 3;
                        pSrc += 3;
                    }
                    //Take the offset into account...
                    p += nOffset;
                    pSrc += nOffset;
                }
            }

            image.UnlockBits(bmData);
            bSrc.UnlockBits(bmSrc);

            return true;
        }


        public static bool ConvolutionRadius2(Bitmap image, ConvolutionMatrix matrix) {
            return true;
        }

    }
}
